﻿#region Using Directives

using System;
using System.IO;

#endregion Using Directives


namespace Edinger.IO
{
    internal sealed class LineScanner
    {
        #region Fields

        private Stream stream;

        private byte[] buffer;
        private int bufferOffset;
        private int bufferLength;

        private long streamOffset;
        private long lineOffset;

        #endregion Fields


        #region Methods

        public bool Read()
        {
            if (bufferLength == 0)
            {
                if (ReadBuffer() == 0)
                    return false;
            }

            lineOffset = streamOffset;

            while (bufferOffset < bufferLength || ReadBuffer() > 0)
            {
                byte b = buffer[bufferOffset];
                if (b == '\r' || b == '\n')
                {
                    streamOffset++;
                    bufferOffset++;

                    if (b == '\r' && (bufferOffset < bufferLength || ReadBuffer() > 0))
                    {
                        if (buffer[bufferOffset] == '\n')
                        {
                            streamOffset++;
                            bufferOffset++;
                        }
                    }

                    return true;
                }

                streamOffset++;
                bufferOffset++;

            }

            return false;
        }


        private int ReadBuffer()
        {
            bufferLength = stream.Read(buffer, 0, buffer.Length);
            bufferOffset = 0;

            return bufferLength;
        }

        #endregion Methods


        #region Properties

        public long LineOffset
        {
            get
            {
                return lineOffset;
            }
        }

        #endregion Properties


        #region Constructors

        public LineScanner(Stream stream)
        {
            this.stream = stream;
            this.buffer = new byte[1024 * 16];
        }

        #endregion Constructors
    }
}
